package wallet

import (
	"context"
	"database/sql"
	"fmt"
	"github.com/zeromicro/go-zero/core/stores/cache"
	"github.com/zeromicro/go-zero/core/stores/sqlx"
	"navi-mumbai/common/gensql"
)

var _ UserTransferFromGameFlowModel = (*customUserTransferFromGameFlowModel)(nil)

type (
	// UserTransferFromGameFlowModel is an interface to be customized, add more methods here,
	// and implement the added methods in customUserTransferFromGameFlowModel.
	UserTransferFromGameFlowModel interface {
		userTransferFromGameFlowModel
		InsertTrans(ctx context.Context, tx sqlx.Session, data *UserTransferFromGameFlow) (sql.Result, error)
		UpdateStateTrans(ctx context.Context, tx sqlx.Session, flowNo int64, exFlow string, state int64) error
		UpdateState(ctx context.Context, flowNo int64, exFlow string, errMsg string, state int64) error
		FindByState(ctx context.Context, uid, providerId, moneyType int64, state int64, pageNo, pageSize int64) ([]*UserTransferFromGameFlow, error)
		CountByState(ctx context.Context, uid, providerId, moneyType int64, state int64) (int64, error)
	}

	customUserTransferFromGameFlowModel struct {
		*defaultUserTransferFromGameFlowModel
		genSql *gensql.GenSql
	}
)

// NewUserTransferFromGameFlowModel returns a model for the database table.
func NewUserTransferFromGameFlowModel(conn sqlx.SqlConn, c cache.CacheConf, opts ...cache.Option) UserTransferFromGameFlowModel {
	return &customUserTransferFromGameFlowModel{
		defaultUserTransferFromGameFlowModel: newUserTransferFromGameFlowModel(conn, c, opts...),
		genSql:                               gensql.NewGenSql(),
	}
}

func (m *customUserTransferFromGameFlowModel) InsertTrans(ctx context.Context, tx sqlx.Session, data *UserTransferFromGameFlow) (sql.Result, error) {
	query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?, ?, ?, ?)", m.table, userTransferFromGameFlowRowsExpectAutoSet)
	ret, err := tx.ExecCtx(ctx, query, data.FlowNo, data.ExternalFlowNo, data.Uid, data.MoneyType, data.MoneyAmount, data.ProviderId, data.State, data.ErrMsg)
	return ret, err
}

func (m *customUserTransferFromGameFlowModel) UpdateStateTrans(ctx context.Context, tx sqlx.Session, flowNo int64, exFlow string, state int64) error {
	query := fmt.Sprintf("update %s set state = ?, external_flow_no = ? where flow_no = ?", m.table)
	rs, err := tx.ExecCtx(ctx, query, state, exFlow, flowNo)
	if err != nil {
		return err
	}
	affected, err := rs.RowsAffected()
	if err != nil {
		return err
	}
	if affected == 0 {
		return ErrNotFound
	}
	return nil
}

func (m *customUserTransferFromGameFlowModel) UpdateState(ctx context.Context, flowNo int64, exFlow string, errMsg string, state int64) error {
	query := fmt.Sprintf("update %s set state = ?, external_flow_no = ?, err_msg = ? where flow_no = ?", m.table)
	rs, err := m.ExecNoCacheCtx(ctx, query, state, exFlow, errMsg, flowNo)
	if err != nil {
		return err
	}
	affected, err := rs.RowsAffected()
	if err != nil {
		return err
	}
	if affected == 0 {
		return ErrNotFound
	}
	return nil
}

func (m *customUserTransferFromGameFlowModel) FindByState(ctx context.Context, uid, providerId, moneyType int64, state int64, pageNo, pageSize int64) ([]*UserTransferFromGameFlow, error) {
	query := fmt.Sprintf("select %s from %s ", userTransferFromGameFlowRows, m.table)
	m.genSql.InitSql(query)

	if uid != 0 {
		m.genSql = m.genSql.Where("uid = ?", uid)
	}
	if providerId != 0 {
		m.genSql = m.genSql.Where("provider_id = ?", providerId)
	}
	if moneyType != 0 {
		m.genSql = m.genSql.Where("money_type = ?", moneyType)
	}
	if state != 0 {
		m.genSql = m.genSql.Where("state = ?", state)
	}

	if pageNo <= 0 {
		pageNo = 1
	}
	if pageSize <= 0 {
		pageSize = 10
	}

	q, v, err := m.genSql.OrderBy("flow_no desc").Limit(uint64(pageSize)).Offset(uint64((pageNo - 1) * pageSize)).ToSql()
	if err != nil {
		return nil, err
	}

	resp := make([]*UserTransferFromGameFlow, 0)
	err = m.QueryRowsNoCacheCtx(ctx, &resp, q, v...)
	switch err {
	case nil:
		return resp, nil
	default:
		return nil, err
	}
}

func (m *customUserTransferFromGameFlowModel) CountByState(ctx context.Context, uid, providerId, moneyType int64, state int64) (int64, error) {
	q := fmt.Sprintf("select count(flow_no) from %s ", m.table)
	m.genSql.InitSql(q)

	query, values, err := m.genSql.Where("uid = ?", uid).Where("provider_id = ?", providerId).Where("money_type = ?", moneyType).Where("state = ?", state).ToSql()
	if err != nil {
		return 0, err
	}

	var resp int64
	err = m.QueryRowNoCacheCtx(ctx, &resp, query, values...)
	switch err {
	case nil:
		return resp, nil
	default:
		return 0, err
	}
}
